iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0
Mobile Development

Android Studio 30天學習紀錄系列 第 25

Android Studio 30天學習紀錄-Day25 QrCode&掃描器

  • 分享至 

  • xImage
  •  

今天要來介紹Qrcode編碼和進行掃描,那麼首先先加入今天的依賴(至gradle)及權限(至Manifest)中:

依賴

    implementation 'com.journeyapps:zxing-android-embedded:4.1.0'
    implementation 'com.google.zxing:core:3.2.1'
    implementation 'me.dm7.barcodescanner:zxing:1.9.4'

權限

因為會用到相機掃描,所以需要打開給相機的權限:

<uses-permission android:name="android.permission.CAMERA" />

Qrcode

Qrcode的部分主要有編碼成QrCode的圖片供掃描、使用Qrcode掃描器解碼取得資料,另外可能還有讀取圖片的Qrcode進行解碼等應用,而在Android中,zxing算是很多人會去用到的Qrcode第三方庫,另外還有swecake、ZBar等,又或者直接將掃描畫面交給surfaceView並搭配BarcodeDetector做使用,而今天會使用zxing的第三方庫來進行實作。
那麼首先先貼上今日UI,並加入掃描的元件(me.dm7.barcodescanner.zxing.ZXingScannerView)至UI中:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/txv_result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:textSize="22dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.509" />

    <ImageView
        android:id="@+id/iv_qrcode"
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.777" />

    <me.dm7.barcodescanner.zxing.ZXingScannerView
        android:id="@+id/scannerView"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

    <Button
        android:id="@+id/btn_scan"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="掃描"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.476"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.452" />

    <Button
        android:id="@+id/btn_encode"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="編碼"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1.0" />

    <EditText
        android:id="@+id/et_encode"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"
        android:hint="編碼內容"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.522"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.93" />
</androidx.constraintlayout.widget.ConstraintLayout>

主程式

首先開始設計主程式,首先會需要先讓使用者許可相機的權限:

//判斷有沒有給CAMERA權限
if(checkSelfPermission(Manifest.permission.CAMERA)
        != PackageManager.PERMISSION_GRANTED){
    //跳是否允許相機權限視窗
    requestPermissions(new String[]{Manifest.permission.CAMERA},1);
}

掃描

接著先從掃描器(ZXingScannerView)開始,他有一些方法:

  • startCamera() : 開啟相機掃描(前提是已打開相機權限)
  • stopCamera() : 關閉相機
  • setResultHandler(this) : 可取得掃描到的資料(前提是class已繼承ZXingScannerView.ResultHandler並繼承handleResult方法)

接著看到繼承:
https://ithelp.ithome.com.tw/upload/images/20221006/20139259bxYegIXgHt.png
繼承完後使用setResultHandler的方法,待掃到資料後便會進到handleResult這個方法,而取出Qrcode內的文字就是:result.getText()

@Override
public void handleResult(Result result) {
    //result.getText()
}

編碼

接著編碼會使用BarcodeEncoder這個元件(如果紅字的話可能要注意gradle有沒有加入完整),使用encodeBitmap這個方法,他會幫你把傳入的字串轉成圖形,接著直接看到使用:

BarcodeEncoder barcodeEncoder = new BarcodeEncoder();
//abc的qrcode圖(輸入編碼字串、編碼樣式、長、寬)
try {
    Bitmap bitmap = barcodeEncoder.encodeBitmap("abc", BarcodeFormat.QR_CODE,200,200);
} catch (WriterException e) {
    e.printStackTrace();
}
//設定圖片至imageView上
//setImageBitmap(bitmap)

主程式

接著並進行設計。

public class MainActivity extends AppCompatActivity implements ZXingScannerView.ResultHandler{
    private Bitmap bitmap;
    private ImageView iv_qrcode;
    private Button btn_scan,btn_encode;
    private EditText et_encode;
    private TextView QRResult;
    ZXingScannerView scannerView;
    BarcodeEncoder barcodeEncoder;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_scan=findViewById(R.id.btn_scan);
        btn_encode=findViewById(R.id.btn_encode);
        iv_qrcode=findViewById(R.id.iv_qrcode);
        et_encode=findViewById(R.id.et_encode);
        QRResult=findViewById(R.id.txv_result);
        scannerView = findViewById(R.id.scannerView);
        barcodeEncoder= new BarcodeEncoder();
        requestPermissions(new String[]{Manifest.permission.CAMERA},1);
        //按下掃描按紐
        btn_scan.setOnClickListener(view->{
            //判斷有沒有給CAMERA權限
            if(checkSelfPermission(Manifest.permission.CAMERA)
                    != PackageManager.PERMISSION_GRANTED){
                //跳是否允許相機權限視窗
                requestPermissions(new String[]{Manifest.permission.CAMERA},1);
            }
            else {
                scannerView.startCamera();
                scannerView.setResultHandler(this);
            }
        });
        btn_encode.setOnClickListener(view->{
            try {
                bitmap = barcodeEncoder.encodeBitmap(et_encode.getText().toString(), BarcodeFormat.QR_CODE,200,200);
            } catch (WriterException e) {
                e.printStackTrace();
            }
            iv_qrcode.setImageBitmap(bitmap);
        });
    }

    @Override
    public void handleResult(Result result) {
        Log.d("Result",""+result.getText());
        QRResult.setText(result.getText());
        scannerView.stopCamera();
    }
}

成果

https://ithelp.ithome.com.tw/upload/images/20221006/20139259NhYCSzf6rm.jpg
https://ithelp.ithome.com.tw/upload/images/20221006/20139259cYFxs4ecVn.jpg
https://ithelp.ithome.com.tw/upload/images/20221006/20139259BnALFXNnvW.jpg


上一篇
Android Studio 30天學習紀錄-Day24 File Stream
下一篇
Android Studio 30天學習紀錄-Day26 MotionLayout動畫
系列文
Android Studio 30天學習紀錄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言